import 'dart:async';
import 'dart:io';

import 'package:amway_superapp_creator_plugin/utils/colors_util.dart';
import 'package:amway_superapp_creator_plugin/utils/logs_util.dart';
import 'package:amway_superapp_creator_plugin/utils/toast_util.dart';
import 'package:amway_superapp_creator_plugin/viewmodels/camera_viewmodel.dart';
import 'package:amway_superapp_creator_plugin/views/base_view.dart';
import 'package:camera/camera.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

class CustomCameraPage extends StatefulWidget {
  @override
  _CustomCameraPageState createState() => _CustomCameraPageState();
}

class _CustomCameraPageState extends State<CustomCameraPage>
    with WidgetsBindingObserver {
  TimerUtil videoTimer;
  CameraController controller;
  List<CameraDescription> cameras;
  bool lampOn = false;
  String videoPath;
  CaptureState _captureState = CaptureState.PHOTO;
  double currentVideoProgress = 0;

  // List<Size> availableSizes=[Size(720,1280),Size(1024,1280)];

  String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();

  Future<Map<Permission, PermissionStatus>> _requestPermission() async {
    return await [
      Permission.camera,
    ].request();
  }

  void _initCamera() async {
    cameras = await availableCameras();
    if (cameras != null) {
      controller = CameraController(cameras[0], ResolutionPreset.high,
          enableAudio: true);
      controller.initialize().then((_) {
        if (!mounted) {
          return;
        }
        setState(() {});
      });
    }
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _requestPermission();
    _initCamera();
  }

  @override
  Widget build(BuildContext context) {
    return BaseView<CameraModelVM>(
      onModelReady: (model) async {},
      builder: (context, model, child) => Scaffold(
        body: cameras == null
            ? Container(
                child: Center(
                  child: Text("加載中..."),
                ),
              )
            : Container(
                width: double.infinity,
                height: double.infinity,
                child: Expanded(
                  flex: 1,
                  child: Stack(
                    alignment: Alignment.center,
                    children: <Widget>[
                      _cameraPreviewWidget(),
                      _cameraUI(model)
                    ],
                  ),
                ),
              ),
      ),
    );
  }

  Widget _cameraPreviewWidget() {
    // Size previewSize = controller.value.previewSize;

    return Container(
      width: double.infinity,
      color: Colors.black,
      child: Center(
        child: AspectRatio(
          aspectRatio: controller.value.aspectRatio,
          child: CameraPreview(controller),
        ),
      ),
    );
  }

  Widget _cameraUI(CameraModelVM model) {
    return Container(
      width: double.infinity,
      height: double.infinity,
      child: Column(
        children: [
          Container(
            width: double.infinity,
            height: ScreenUtil().setHeight(100),
            child: Row(
              children: [
                Padding(
                  padding: EdgeInsets.all(ScreenUtil().setWidth(10)),
                  child: Image.asset('picture/icon_dialogClose.png',
                      package: 'amway_superapp_creator_plugin',
                      width: ScreenUtil().setWidth(18),
                      height: ScreenUtil().setWidth(18),
                      color: Colors.white),
                ),
                GestureDetector(
                    onTap: () {},
                    child: Expanded(
                        child: Center(
                            child: Text(
                      '16:9',
                      style: TextStyle(color: Colors.white),
                    ))))
              ],
            ),
          ),
          Expanded(
              child: Stack(
            fit: StackFit.loose,
            alignment: Alignment.bottomCenter,
            children: [
              Positioned(
                  bottom: ScreenUtil().setHeight(151),
                  right: ScreenUtil().setWidth(51),
                  child: GestureDetector(
                    onTap: () {
                      switchCamera();
                    },
                    child: Image.asset(
                      'picture/icon_switch_camera.png',
                      width: ScreenUtil().setHeight(32),
                      height: ScreenUtil().setHeight(32),
                    ),
                  )),
              Positioned(
                  bottom: ScreenUtil().setHeight(151),
                  left: ScreenUtil().setWidth(51),
                  child: GestureDetector(
                    onTap: () {
                      switchLamp();
                    },
                    child: Image.asset(
                      'picture/icon_switch_flash.png',
                      width: ScreenUtil().setHeight(32),
                      height: ScreenUtil().setHeight(32),
                    ),
                  )),
              Positioned(
                  bottom: ScreenUtil().setHeight(120),
                  child: _captureButton(model)),
            ],
          )),
          Container(
            width: double.infinity,
            height: ScreenUtil().setHeight(100),
            child: DefaultTabController(
              length: 3,
              child: TabBar(
                isScrollable: false,
                onTap: (index) {
                  setState(() {
                    switch (index) {
                      case 0:
                        if (_captureState == CaptureState.VIDEO_STARTED) {
                          onStopButtonPressed();
                        } else {
                          _captureState = CaptureState.NONE;
                        }
                        break;
                      case 1:
                        if (_captureState == CaptureState.VIDEO_STARTED) {
                        } else {
                          _captureState = CaptureState.VIDEO_NOT_STARTED;
                        }
                        break;
                      case 2:
                        if (_captureState == CaptureState.VIDEO_STARTED) {
                          onStopButtonPressed();
                        } else {
                          _captureState = CaptureState.PHOTO;
                        }
                        break;
                    }
                  });
                },
                tabs: [
                  new Tab(text: '相册'),
                  new Tab(text: '拍视频'),
                  new Tab(text: '拍照'),
                ],
                indicatorColor: Colors.white,
              ),
            ),
            // child: Row(
            //   mainAxisSize: MainAxisSize.max,
            //   mainAxisAlignment: MainAxisAlignment.spaceAround,
            //   crossAxisAlignment: CrossAxisAlignment.stretch,
            //                 children: _buildBottomTabs(),
            // ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller?.dispose();
    if (videoTimer != null && videoTimer.isActive()) {
      videoTimer.cancel();
      videoTimer = null;
    }
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (mounted) {
        if (filePath != null) {
          Navigator.of(context).pop(filePath);
        }
      }
    });
  }

  Future<String> takePicture() async {
    if (!controller.value.isInitialized) {
      print('Error: select a camera first.');
      return null;
    }
    final Directory extDir = await getExternalStorageDirectory();
    final String dirPath = '${extDir.path}/camera/';
    await Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/${timestamp()}.jpg';

    if (controller.value.isTakingPicture) {
      // A capture is already pending, do nothing.
      return null;
    }
    try {
      await controller.takePicture(filePath);
    } on CameraException catch (e) {
      print("出现异常$e");
      return null;
    }
    return filePath;
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // App state changed before we got the chance to initialize.
    if (controller == null || !controller.value.isInitialized) {
      return;
    }
    if (state == AppLifecycleState.inactive) {
      controller?.dispose();
    } else if (state == AppLifecycleState.resumed) {
      if (controller != null) {
        onNewCameraSelected(controller.description);
      }
    }
  }

  // void onResolutionSwitched(CameraDescription cameraDescription) async{
  //   if (controller != null) {
  //     await controller.dispose();
  //   }
  //
  // }

  void switchCamera() {
    if (controller != null &&
        controller.value.isInitialized &&
        cameras.length == 2) {
      if (controller.description.lensDirection == cameras[0].lensDirection) {
        onNewCameraSelected(cameras[1]);
      } else {
        onNewCameraSelected(cameras[0]);
      }
    }
  }

  void switchLamp() async {
    // bool hasLamp = await TorchCompat.hasTorch;
    // if (hasLamp) {
    //   if (lampOn) {
    //     TorchCompat.turnOff();
    //   } else {
    //     TorchCompat.turnOn();
    //   }
    // } else {}
  }

  void onNewCameraSelected(CameraDescription cameraDescription) async {
    if (controller != null) {
      await controller.dispose();
    }
    controller = CameraController(
      cameraDescription,
      ResolutionPreset.high,
      enableAudio: true,
    );

    // If the controller is updated then update the UI.
    controller.addListener(() {
      if (mounted) setState(() {});
      if (controller.value.hasError) {
        ToastUtils.showLongToast(
            'Camera error ${controller.value.errorDescription}');
      }
    });

    try {
      await controller.initialize();
    } on CameraException catch (e) {
      _showCameraException(e);
    }

    if (mounted) {
      setState(() {});
    }
  }

  void onVideoRecordButtonPressed() {
    startVideoRecording().then((String filePath) {
      if (mounted)
        setState(() {
          _captureState = CaptureState.VIDEO_STARTED;
          videoTimer = TimerUtil(mInterval: 1000, mTotalTime: 1000 * 60 * 5);
          videoTimer.setOnTimerTickCallback((millisUntilFinished) {
            print(millisUntilFinished / (60 * 5));
            setState(() {
              currentVideoProgress = millisUntilFinished / (60 * 5);
            });
          });
          videoTimer.startTimer();
        });
      if (filePath != null)
        ToastUtils.showShortToast('Saving video to $filePath');
    });
  }

  void onStopButtonPressed() {
    stopVideoRecording().then((_) {
      if (mounted)
        setState(() {
          _captureState = CaptureState.NONE;
          if (videoTimer != null && videoTimer.isActive()) {
            videoTimer.cancel();
            videoTimer = null;
            currentVideoProgress = 0;
          }
        });
      ToastUtils.showShortToast('Video recorded to: $videoPath');
    });
  }

  void onPauseButtonPressed() {
    pauseVideoRecording().then((_) {
      if (mounted) setState(() {});
      ToastUtils.showShortToast('Video recording paused');
    });
  }

  void onResumeButtonPressed() {
    resumeVideoRecording().then((_) {
      if (mounted) setState(() {});
      ToastUtils.showShortToast('Video recording resumed');
    });
  }

  void _showCameraException(CameraException e) {
    LogsUtil.e(e.code, e.description);
    ToastUtils.showLongToast('Error: ${e.code}\n${e.description}');
  }

  Future<String> startVideoRecording() async {
    if (!controller.value.isInitialized) {
      ToastUtils.showShortToast('相机不可用');
      return null;
    }

    final Directory extDir = await getExternalStorageDirectory();
    final String dirPath = '${extDir.path}/camera';
    await Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/${timestamp()}.mp4';

    if (controller.value.isRecordingVideo) {
      // A recording is already started, do nothing.
      return null;
    }

    try {
      videoPath = filePath;
      await controller.startVideoRecording(filePath);
    } on CameraException catch (e) {
      _showCameraException(e);
      return null;
    }
    return filePath;
  }

  Future<void> stopVideoRecording() async {
    if (!controller.value.isRecordingVideo) {
      return null;
    }

    try {
      await controller.stopVideoRecording();
    } on CameraException catch (e) {
      _showCameraException(e);
      return null;
    }

    // await _startVideoPlayer();
  }

  Future<void> pauseVideoRecording() async {
    if (!controller.value.isRecordingVideo) {
      return null;
    }

    try {
      await controller.pauseVideoRecording();
    } on CameraException catch (e) {
      _showCameraException(e);
      rethrow;
    }
  }

  Future<void> resumeVideoRecording() async {
    if (!controller.value.isRecordingVideo) {
      return null;
    }

    try {
      await controller.resumeVideoRecording();
    } on CameraException catch (e) {
      _showCameraException(e);
      rethrow;
    }
  }

  Widget _captureButton(CameraModelVM vm) {
    return GestureDetector(
      onTap: () {
        if (_captureState == CaptureState.PHOTO) {
          onTakePictureButtonPressed();
        } else if (_captureState == CaptureState.VIDEO_NOT_STARTED) {
          onVideoRecordButtonPressed();
        } else if (_captureState == CaptureState.VIDEO_STARTED) {
          onStopButtonPressed();
        }
      },
      child: Container(
        child: Stack(
          alignment: Alignment.center,
          children: [
            Container(
              width: ScreenUtil().setHeight(60),
              height: ScreenUtil().setHeight(60),
              child: Center(
                  child: CustomPaint(
                painter: CircleProgressBarPainter(
                    ColorUtil.fromHex('#7C7C7C').withOpacity(0.3),
                    Colors.red.withOpacity(0.6),
                    270,
                    currentVideoProgress * 360,
                    360,
                    ScreenUtil().setWidth(20)),
                size: Size(
                    ScreenUtil().setHeight(60), ScreenUtil().setHeight(60)),
              )),
            ),
            CircleAvatar(
                backgroundColor: ColorUtil.fromHex('#7C7C7C'),
                radius: ScreenUtil().setHeight(28)),
          ],
        ),
        width: ScreenUtil().setHeight(75),
        height: ScreenUtil().setHeight(75),
      ),
    );
  }
}

/// 绘制进度条
class CircleProgressBarPainter extends CustomPainter {
  var _paintBckGround;
  var _paintFore;

  final _strokeWidth;
  final _backgroundColor;
  final _foreColor;
  final _startAngle;
  final _sweepAngle;
  final _endAngle;

  CircleProgressBarPainter(this._backgroundColor, this._foreColor,
      this._startAngle, this._sweepAngle, this._endAngle, this._strokeWidth) {
    _paintBckGround = new Paint()
      ..color = _backgroundColor
      ..isAntiAlias = true
      ..strokeCap = StrokeCap.round
      ..strokeWidth = _strokeWidth
      ..style = PaintingStyle.stroke;

    _paintFore = new Paint()
      ..color = _foreColor
      ..isAntiAlias = true
      ..strokeWidth = _strokeWidth
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke;
  }

  @override
  void paint(Canvas canvas, Size size) {
    var radius = size.width > size.height ? size.width / 2 : size.height / 2;
    //圆
    canvas.drawCircle(Offset(radius, radius), radius, _paintBckGround);
    //半圆
    Rect rect = Rect.fromCircle(center: Offset(radius, radius), radius: radius);
    canvas.drawArc(rect, _startAngle / 180 * 3.14, _sweepAngle / 180 * 3.14,
        false, _paintFore);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return _sweepAngle != _endAngle;
  }
}
